///////////////////////////////////////////////////////////////
//	File Name	:	"CGame.h"
//
//	Author Name	:	Michael Schoell (MS)
//	
//	Purpose		:	To encapsulate all game related code.
///////////////////////////////////////////////////////////////

#include "CGame.h"
#include "CMainMenuState.h"
#include "CGamePlayState.h"
#include "CMessageSystem.h"

//	Proper Singleton:
//		Constructor
CGame::CGame(void)
{
	m_pD3D	= NULL;
	m_pDI	= NULL;
	m_pDS	= NULL;
	m_pTM	= NULL;
	m_pWM	= NULL;
	m_pGameState = NULL;


	m_nScreenWidth = 800;
	m_nScreenHeight = 600;
	m_bIsWindowed = true;

	m_fElapsedTime = 0;
	m_dwPrevTime = GetTickCount();
}

//		Destructor
CGame::~CGame(void)
{

}

//	Singleton accessor
CGame* CGame::GetInstance(void)
{
	static CGame instance;
	return &instance;
}

//	3 steps a game goes through in its lifetime.
//		1.	Initialization
void CGame::Initialize(HWND hWnd, HINSTANCE hInstance,
					   int nScreenWidth, int nScreenHeight, bool bIsWindowed)
{
	m_pD3D	= CSGD_Direct3D::GetInstance();
	m_pDI	= CSGD_DirectInput::GetInstance();
	m_pDS	= CSGD_DirectSound::GetInstance();
	m_pTM	= CSGD_TextureManager::GetInstance();
	m_pWM	= CSGD_WaveManager::GetInstance();

	m_pD3D->InitDirect3D(hWnd, nScreenWidth, nScreenHeight, bIsWindowed, false);
	m_pTM->InitTextureManager(m_pD3D->GetDirect3DDevice(), m_pD3D->GetSprite());
	m_pDS->InitDirectSound(hWnd);
	m_pWM->InitWaveManager(hWnd, m_pDS->GetDSObject());
	m_pDI->InitDirectInput(hWnd, hInstance, DI_KEYBOARD | DI_MOUSE );
	
	CMessageSystem::GetInstance()->InitMessageSystem( CGame::MessageProc );
	//m_nImageID = m_pTM->LoadTexture("resource/SGD_ship.bmp", D3DCOLOR_XRGB(0, 0, 0));
	//m_nSoundID = m_pWM->LoadWave("resource/SGD_sfx1.wav");

	m_nScreenWidth = nScreenWidth;
	m_nScreenHeight = nScreenHeight;
	m_bIsWindowed = bIsWindowed;

	ChangeState(CMainMenuState::GetInstance());
}

//		3.	Clean Up
void CGame::Shutdown(void)
{
	ChangeState(NULL);

	if(m_pDI)
	{
		m_pDI->ShutdownDirectInput();
		m_pDI = NULL;
	}

	if(m_pWM)
	{
		m_pWM->ShutdownWaveManager();
		m_pDI = NULL;
	}

	if(m_pDS)
	{
		m_pDS->ShutdownDirectSound();
		m_pDS = NULL;
	}

	if(m_pTM)
	{
		m_pTM->ShutdownTextureManager();
		m_pTM = NULL;
	}

	if(m_pD3D)
	{
		m_pD3D->ShutdownDirect3D();
		m_pD3D = NULL;
	}

}

//		2.	Execution
bool CGame::Main(void)
{
	DWORD dwCurrTime = GetTickCount();

	m_fElapsedTime = (float)(dwCurrTime - m_dwPrevTime) / 1000;

	m_dwPrevTime = dwCurrTime;

	if(Input() == false)
		return false;

	Update();
	Render();
	return true;
}

bool CGame::Input(void)
{
	m_pDI->ReadDevices(); //	Once a frame.
	
	if((m_pDI->KeyDown(DIK_LALT) || m_pDI->KeyDown(DIK_RALT)) && m_pDI->KeyDown(DIK_RETURN))
	{
		m_bIsWindowed = !m_bIsWindowed;
		m_pD3D->ChangeDisplayParam(m_nScreenWidth, m_nScreenHeight, m_bIsWindowed);
	}
	else if(m_pGameState->Input())
		return false;

	return true;
}

void CGame::Update(void)
{
	//clean up excess copies of waves.
	m_pWM->Update();
	m_pGameState->Update(m_fElapsedTime);

}

void CGame::Render(void)
{
	m_pGameState->Render();
}

void CGame::ChangeState(IGameState* pGameState)
{
	if(m_pGameState)
	{
		m_pGameState->Exit();
		m_pGameState = NULL;
	}

	m_pGameState = pGameState;

	if(m_pGameState)
		m_pGameState->Enter();
}
void CGame::HandleEvents( CEvents* pEvents )
{
}
void CGame::MessageProc( CMessager* pMsg )
{
	switch( pMsg->GetMessageID() )
	{
	case MSG_CREATE_PLAYER:
		{
			CGamePlayState* pGameState = CGamePlayState::GetInstance();
			CCreatePlayerMessage* pCPM = (CCreatePlayerMessage*)pMsg;
			
			CPlayer* pPlayer = (CPlayer*)pGameState->GetFactory()->CreateObject("CPlayer");
			pPlayer->SetPosX( pCPM->GetPosX() );
			pPlayer->SetPosY( pCPM->GetPosY() );
			pPlayer->SetVelX( pCPM->GetVelX() );
			pPlayer->SetVelY( pCPM->GetVelY() );
			pPlayer->SetImageID( pCPM->GetImageID() );
			pPlayer->SetWidth( pCPM->GetWidth() );
			pPlayer->SetHeight( pCPM->GetHeight() );

			pGameState->GetManager()->AddObject( pPlayer );
			pPlayer->Release();
			break;
		}
	case MSG_DESTROY_PLAYER:
		{
			CGamePlayState* pGameState = CGamePlayState::GetInstance();
			CDestroyPlayerMessage* pDPM = (CDestroyPlayerMessage*)pMsg;
			pGameState->GetManager()->RemoveObject( pDPM->GetPlayerToDestroy() );
			break;
		}
	case MSG_CREATE_ENEMY:
		{
			CGamePlayState* pGameState = CGamePlayState::GetInstance();
			CCreateEnemyMessage* pCPM = (CCreateEnemyMessage*)pMsg;
			CEnemy* pEnemy = (CEnemy*)pGameState->GetFactory()->CreateObject("CEnemy");
			pEnemy->SetPosX( pCPM->GetPosX() );
			pEnemy->SetPosY( pCPM->GetPosY() );
			pEnemy->SetVelX( pCPM->GetVelX() );
			pEnemy->SetVelY( pCPM->GetVelY() );
			pEnemy->SetImageID( pCPM->GetImageID() );
			pEnemy->SetWidth( pCPM->GetWidth() );
			pEnemy->SetHeight( pCPM->GetHeight() );

			pGameState->GetManager()->AddObject( pEnemy );
			pEnemy->Release();
			break;
		}
	case MSG_DESTROY_ENEMY:
		{
			CGamePlayState* pGameState = CGamePlayState::GetInstance();
			CDestroyEnemyMessage* pDEM = (CDestroyEnemyMessage*)pMsg;
			pGameState->GetManager()->RemoveObject( pDEM->GetEnemyToDestroy() );
			break;
		}
	case MSG_CREATE_POWERUP:
		{
			break;
		}
	case MSG_DESTROY_POWERUP:
		{
			break;
		}
	};
}